#include "RepresentationEngine.hpp"

// GLUT handlers:
static RepresentationEngine* representationEngineInstance;

void displayHandler() {
    representationEngineInstance->handleDisplay();
}

void keyboardHandler(unsigned char key, int x, int y) {
    representationEngineInstance->handleKey(key, x, y);
}

void keyboardUpHandler(unsigned char key, int x, int y) {
    representationEngineInstance->handleKeyUp(key, x, y);
}

void mouseHandler(int button, int state, int x, int y) {
    representationEngineInstance->handleMouse(button, state, x, y);
}

void reshapeHandler(int width, int height) {
    representationEngineInstance->handleReshape(width, height);
}

void specialHandler(int key, int x, int y) {
    representationEngineInstance->handleSpecialKey(key, x, y);
}

void specialUpHandler(int key, int x, int y) {
    representationEngineInstance->handleSpecialKeyUp(key, x, y);
}

// RepresentationEngine implementation:

RepresentationEngine::RepresentationEngine(GameEngine* gameEngine) {
    representationEngineInstance = this;
    this->gameEngine = gameEngine;

    // GLUT Initialization.
    int argc = 0;
    char* argv[0];
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(800, 600);
    glutCreateWindow("LIGHT TEST #1");
    glutSetCursor(GLUT_CURSOR_NONE);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glutIgnoreKeyRepeat(true);

    // Handler assignation.
    glutDisplayFunc(displayHandler);
    glutIdleFunc(displayHandler);
    glutKeyboardFunc(keyboardHandler);
    glutKeyboardUpFunc(keyboardUpHandler);
    glutMouseFunc(mouseHandler);
    glutReshapeFunc(reshapeHandler);
    glutSpecialFunc(specialHandler);
    glutSpecialUpFunc(specialUpHandler);


    // Alpha channel.
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

RepresentationEngine::~RepresentationEngine() {
    // TODO: cerrar la ventana.
}

float RepresentationEngine::getElapsedTime() {
    return (float)glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
}

void RepresentationEngine::handleDisplay() {
    this->gameEngine->render();
}

void RepresentationEngine::handleKey(unsigned char key, int mouseX, int mouseY) {
    this->gameEngine->handleKey(key);
}

void RepresentationEngine::handleKeyUp(unsigned char key, int mouseX, int mouseY) {
    this->gameEngine->handleKeyUp(key);
}

void RepresentationEngine::handleMouse(int button, int state, int x, int y) {
    if (state == GLUT_DOWN) {
        this->gameEngine->handleMouseButtonDown(button);
    }
    else if (state == GLUT_UP) {
        this->gameEngine->handleMouseButtonUp(button);
    }
}

void RepresentationEngine::handleReshape(int width, int height) {
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Calculate the aspect ratio and set the clipping volume.
    gluPerspective(45, (float)width / (float)height, 0.1f, 100.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void RepresentationEngine::handleSpecialKey(int key, int x, int y) {
    this->gameEngine->handleSpecialKey(key);
}

void RepresentationEngine::handleSpecialKeyUp(int key, int x, int y) {
    this->gameEngine->handleSpecialKeyUp(key);
}

void RepresentationEngine::runMainLoop() {
    glutMainLoop();
}

void RepresentationEngine::zoomIn() {
}

void RepresentationEngine::zoomOut() {
}
